Git 的 HEAD 指针
这部分转载自 Git-你好, HEAD 同学
Git 的 HEAD 指针
Head 指针可以指向快照节点也可以指向 branch。当指向 branch 时提交后会和 branch指针一起向后移动,当不指向 branch提交时时则会在一个 detached(游离)状态。
HEAD 在哪?HEAD 是谁?
第一步,我们先要去找到 HEAD。找之前,先考大家一个问题:
Git 是怎么和项目联系起来的呢?
在执行第一个 git
命令操作 git init
的时候,在项目的根目录下,创建了一个 .git
文件夹, 此文件是隐藏文件
打开 .git
,可看到如下内容:
.git
文件中存储 Git 对这个项目进行版本控制的所有信息,同时可以发现这里面有一个文件叫做 HEAD
打开这个文件可以发现它是指向了另一个文件的应用,于是找的 refs/heads/master
打开(如果刚创建的目录是不存在这个文件的,得有 “历史” 记录才行)
可以通过 git show
命令来查看 HEAD
指针目前指向什么。
HEAD 的本质是什么?
通过 git log
查看,可以发现是上面 master 文件的内容是 master 分支最新的提交。
所以目前 HEAD 文件指向的内容是传递顺序是这样的:
HEAD -> refs/heads/master -> b003ebaff6916c3aa86b2a51bfea15b52686bbc0
得出了一个结论,HEAD 的本质不是提向分支,而是指向 commit 提交。
问题又来了:
- HEAD 为什么要通过 refs/heads/master 中转一下,而不是直接指向 master 分支的提交?
- HEAD 可以直接指向提交吗?
解释以上问题,需要知道 refs/heads/
文件夹存储的内容是当前项目所有分支的头指针,每个分支的头指针都指向该分支的最新提交。
从上图看,三个分支的头指针指向的提交都不同,HEAD直接指向提交毫无问题。
但是此时出现一个 dev 分支,刚从 master 检出,头指针和 master 相同,HEAD直接指向提交的话,怎么知道,当前工作分支是 master 还是 dev 呢?
此时 HEAD 文件的内容就非常有意义了:
所以,HEAD 通过先指向分支的头指针,再指向提交的意义就是表明当前所处的分支。
关于第二个问题,答案是肯定的,但是会进入一种特殊的状态 detached HEAD。
detached HEAD
使用 git checkout <commit id>
成功的进入了
detached HEAD 状态:
此时的 HEAD 文件内容,不再指向分支的头指针,而是直接指向了提交。
得出结论,当 HEAD 指针直接指向提交时,就会导致 detached HEAD
状态。在这个状态下,如果创建了新提交,新提交不属于任何分支。相对应的,现存的所有分支也不会受 detached HEAD
状态提交的影响。
这个状态并不是坏事,在某些特殊的场景下你可能会需要它。
例如:
排查问题的时候,checkout 到怀疑的 commit 点上去做些测试,detached HEAD
会保护你的现有分支不受影响,测试完了不想保存直接 checkout 到其他地方,可以放弃修改,想保存修改,可以创建一个 git checkout -b <new-branch-name>
新分支保存。
除了 git checkout <commit id>
,还有一个命令可以进入 detached HEAD 状态。
# HEAD 直接脱离分支头指针,指向分支头指针指向的 commit
git checkout --detach
移动分支到 detached
移动已存在的分支到 detached 状态的分支
git branch -f master C2
这个时候 master 分支以前的快照 C3就变成了 detached 状态了